package coupon_logic

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"time"
	"wx-uniapp-go/internal/repository/dto"
	"wx-uniapp-go/internal/repository/models"
)

// ReceiveCoupon 领取优惠券
func (l *CouponLogic) ReceiveCoupon(req *dto.ReceiveCouponReq) error {
	// 获取优惠券规则
	rule := new(models.CouponRule)
	exists, err := models.Get(l.Ctx, rule, "id = ? AND status = 1", req.RuleId)
	if err != nil {
		return err
	}
	if !exists {
		return errors.New("优惠券规则不存在或已禁用")
	}

	// 检查每日限制
	if rule.DayLimit > 0 {
		today := time.Now().Format("2006-01-02")
		count, err := models.Count(l.Ctx, &models.UserCoupon{},
			"user_id = ? AND rule_id = ? AND DATE(create_time) = ?",
			req.UserId, req.RuleId, today)
		if err != nil {
			return err
		}
		if count >= int64(rule.DayLimit) {
			return errors.New("已达到每日领取限制")
		}
	}

	// 检查总领取限制
	if rule.TotalLimit > 0 {
		count, err := models.Count(l.Ctx, &models.UserCoupon{},
			"user_id = ? AND rule_id = ?", req.UserId, req.RuleId)
		if err != nil {
			return err
		}
		if count >= int64(rule.TotalLimit) {
			return errors.New("已达到总领取限制")
		}
	}

	// 开启事务
	ctx := models.BeginTransaction(l.Ctx)

	// 创建用户优惠券
	now := time.Now()
	userCoupon := &models.UserCoupon{
		UserId:     req.UserId,
		RuleId:     req.RuleId,
		Type:       rule.Type,
		Value:      rule.Value,
		MinAmount:  rule.MinAmount,
		Status:     models.CouponStatusUnused,
		ValidStart: now,
		ValidEnd:   now.AddDate(0, 0, rule.ValidDays),
	}

	if _, err = models.Insert(ctx, userCoupon); err != nil {
		return err
	}

	// 记录领取日志
	couponLog := &models.CouponLog{
		UserId:   req.UserId,
		CouponId: userCoupon.Id,
		Type:     models.CouponLogTypeReceive,
		Remark:   "领取优惠券",
	}

	if _, err = models.Insert(ctx, couponLog); err != nil {
		return err
	}

	return nil
}

// ListUserCoupons 查询用户优惠券列表
func (l *CouponLogic) ListUserCoupons(req *dto.ListUserCouponReq) (*dto.ListUserCouponResp, error) {
	where := "user_id = ?"
	var params []interface{}
	params = append(params, req.UserId)

	// 状态筛选
	if req.Status > 0 {
		where += " AND status = ?"
		params = append(params, req.Status)
	}

	// 检查过期状态
	now := time.Now()
	where += " AND (status != ? OR (status = ? AND valid_end > ?))"
	params = append(params, models.CouponStatusExpired, models.CouponStatusUnused, now)

	// 获取总数
	total, err := models.Count(l.Ctx, &models.UserCoupon{}, where, params...)
	if err != nil {
		return nil, err
	}

	// 获取列表
	var coupons []*models.UserCoupon
	_, err = models.FindByPage(l.Ctx, &coupons, req.Page, req.Size, where, params...)
	if err != nil {
		return nil, err
	}

	// 获取规则ID列表
	ruleIds := make([]int64, 0, len(coupons))
	for _, coupon := range coupons {
		ruleIds = append(ruleIds, coupon.RuleId)
	}

	// 批量获取规则信息
	var rules []*models.CouponRule
	if len(ruleIds) > 0 {
		ruleWhere := "id IN (" + buildInParams(ruleIds) + ")"
		err = models.Find(l.Ctx, &rules, ruleWhere, convertToInterface(ruleIds)...)
		if err != nil {
			return nil, err
		}
	}

	// 构建规则映射
	ruleMap := make(map[int64]*models.CouponRule)
	for _, rule := range rules {
		ruleMap[rule.Id] = rule
	}

	// 转换响应
	list := make([]*dto.UserCouponResp, len(coupons))
	for i, coupon := range coupons {
		// 检查是否已过期但状态未更新
		if coupon.Status == models.CouponStatusUnused && coupon.ValidEnd.Before(now) {
			coupon.Status = models.CouponStatusExpired
			// 异步更新状态
			go l.updateCouponStatus(coupon.Id, models.CouponStatusExpired)
		}

		list[i] = &dto.UserCouponResp{
			Id:          coupon.Id,
			Type:        coupon.Type,
			Value:       coupon.Value,
			MinAmount:   coupon.MinAmount,
			Status:      coupon.Status,
			ValidStart:  coupon.ValidStart,
			ValidEnd:    coupon.ValidEnd,
			Description: ruleMap[coupon.RuleId].Description,
			Name:        ruleMap[coupon.RuleId].Name,
			ProductType: ruleMap[coupon.RuleId].ProductType,
		}
	}

	return &dto.ListUserCouponResp{
		Total: total,
		List:  list,
	}, nil
}

// 构建IN查询参数
func buildInParams(ids []int64) string {
	params := make([]string, len(ids))
	for i := range ids {
		params[i] = "?"
	}
	return strings.Join(params, ",")
}

// 转换为interface切片
func convertToInterface(ids []int64) []interface{} {
	params := make([]interface{}, len(ids))
	for i, id := range ids {
		params[i] = id
	}
	return params
}

// 异步更新优惠券状态
func (l *CouponLogic) updateCouponStatus(couponId int64, status int) {
	ctx := context.Background()
	coupon := &models.UserCoupon{
		Id:     couponId,
		Status: status,
	}
	_ = models.Update(ctx, fmt.Sprintf("id = %d", couponId), coupon)

	// 记录状态变更日志
	if status == models.CouponStatusExpired {
		log := &models.CouponLog{
			CouponId: couponId,
			Type:     models.CouponLogTypeExpire,
			Remark:   "优惠券过期",
		}
		_, _ = models.Insert(ctx, log)
	}
}
